package net.zdsoft.wpchat.support.dao.impl;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collections;
import java.util.List;
import java.util.Map;

import net.zdsoft.keel.jdbc.JdbcBasicDao;
import net.zdsoft.keel.jdbc.MapRowMapper;
import net.zdsoft.keel.jdbc.MultiRowMapper;
import net.zdsoft.keel.util.Validators;
import net.zdsoft.wpchat.support.dao.AuthDao;
import net.zdsoft.wpchat.support.entity.AuthCatalog;
import net.zdsoft.wpchat.support.entity.AuthModule;
import net.zdsoft.wpchat.support.entity.AuthOperation;
import net.zdsoft.wpchat.support.entity.GroupPermission;
import net.zdsoft.wpchat.support.service.AuthCacheService;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Repository;

/**
 * 权限dao实现
 *
 * @author xuan
 */
@Repository
public class AuthDaoImpl extends JdbcBasicDao implements AuthDao {
	private static final Logger log = LoggerFactory.getLogger(AuthCacheService.class);

	private static final String SQL_FIND_ALL_CATALOG = "SELECT * FROM su_auth_catalog WHERE state=1";
	private static final String SQL_FIND_ALL_MODULE = "SELECT * FROM su_auth_module WHERE state=1";
	private static final String SQL_FIND_ALL_OPERATION = "SELECT * FROM su_auth_operation WHERE state=1";
	private static final String SQL_FIND_OPERATIONS_BY_GROUP_IDS = "SELECT * FROM su_group_permission WHERE group_id IN";
	private static final String SQL_FIND_GROUP_NAMES_BY_IDS = "SELECT * FROM su_group WHERE id IN";

	@Override
	public Map<String, AuthCatalog> findCatalogMap() {
		return queryForMap(SQL_FIND_ALL_CATALOG, new AuthCatalogMapRowMapper());
	}

	@Override
	public Map<String, AuthModule> findModuleMap(
			Map<String, AuthCatalog> catalogMap) {
		return queryForMap(SQL_FIND_ALL_MODULE, new AuthModuleMapReader(
				catalogMap));
	}

	@Override
	public Map<String, AuthOperation> findOperationMap(
			Map<String, AuthModule> moduleMap) {
		return queryForMap(SQL_FIND_ALL_OPERATION, new AuthOperationMapReader(
				moduleMap));
	}

	@Override
	public List<GroupPermission> findGroupPerms(String[] groupIds) {
		if (Validators.isEmpty(groupIds)) {
			return Collections.emptyList();
		}
		return queryForInSQL(SQL_FIND_OPERATIONS_BY_GROUP_IDS, null, groupIds,
				new GroupPermMultiRowMapper());
	}

	@Override
	public List<String> findGroupNames(String[] groupIds) {
		if (Validators.isEmpty(groupIds)) {
			return Collections.emptyList();
		}
		return queryForInSQL(SQL_FIND_GROUP_NAMES_BY_IDS, null, groupIds,
				new MultiRowMapper<String>() {
					@Override
					public String mapRow(ResultSet rs, int rowNum)
							throws SQLException {
						return rs.getString("name");
					}
				});
	}

	/**
	 * AuthCatalog的map集
	 *
	 * @author xuan
	 */
	private static class AuthCatalogMapRowMapper implements MapRowMapper<String, AuthCatalog> {
		@Override
		public String mapRowKey(ResultSet rs, int rowNum) throws SQLException {
			return rs.getString("id");
		}

		@Override
		public AuthCatalog mapRowValue(ResultSet rs, int rowNum) throws SQLException {
			AuthCatalog catalog = new AuthCatalog();
			catalog.setId(rs.getString("id"));
			catalog.setNamespace(rs.getString("namespace"));
			catalog.setDisplayOrder(rs.getInt("display_order"));
			catalog.setName(rs.getString("name"));
			catalog.setState(rs.getInt("state"));
			catalog.setVisible(1 == rs.getInt("is_visible"));
			return catalog;
		}
	}

	/**
	 * AuthModule的map集
	 *
	 * @author xuan
	 */
	private static class AuthModuleMapReader implements MapRowMapper<String, AuthModule> {
		private Map<String, AuthCatalog> catalogMap = null;
		public AuthModuleMapReader(Map<String, AuthCatalog> catalogMap) {
			this.catalogMap = catalogMap;
		}

		@Override
		public String mapRowKey(ResultSet rs, int rowNum) throws SQLException {
			return rs.getString("id");
		}

		@Override
		public AuthModule mapRowValue(ResultSet rs, int rowNum) throws SQLException {
			AuthModule module = new AuthModule();

			String catalogId = rs.getString("auth_catalog_id");
			AuthCatalog catalog = catalogMap.get(catalogId);
			if (null == catalog) {
				log.error("Could not find catalog[" + catalogId + "]");
			}
			module.setCatalog(catalog);
			module.setId(rs.getString("id"));
			module.setName(rs.getString("name"));
			module.setVisible(1 == rs.getInt("is_visible"));
			module.setDisplayOrder(rs.getInt("display_order"));

			String parameter = rs.getString("parameter");
			module.setParameters(Validators.isEmpty(parameter) ? new String[0]
					: parameter.split(","));

			String condition = rs.getString("condition2");
			module.setConditions(Validators.isEmpty(condition) ? new String[0]
					: condition.split(","));

			String preModule = rs.getString("pre_auth_module");
			module.setPreModules(Validators.isEmpty(preModule) ? new String[0]
					: preModule.split(","));

			module.setState(rs.getInt("state"));
			module.setType(rs.getInt("type"));
			return module;
		}
	}

	/**
	 * AuthOperation的map集
	 *
	 * @author xuan
	 */
	private static class AuthOperationMapReader implements MapRowMapper<String, AuthOperation> {
		private Map<String, AuthModule> moduleMap = null;
		public AuthOperationMapReader(Map<String, AuthModule> moduleMap) {
			this.moduleMap = moduleMap;
		}

		@Override
		public String mapRowKey(ResultSet rs, int rowNum) throws SQLException {
			return rs.getString("id");
		}

		@Override
		public AuthOperation mapRowValue(ResultSet rs, int rowNum) throws SQLException {
			AuthOperation operation = new AuthOperation();

			String moduleId = rs.getString("auth_module_id");
			AuthModule module = moduleMap.get(moduleId);
			if (null == module) {
				log.error("Could not find module[" + moduleId + "]");
			}
			operation.setModule(module);

			operation.setId(rs.getString("id"));
			operation.setName(rs.getString("name"));

			String scope = rs.getString("scope");
			operation.setScope(Validators.isEmpty(scope) ? new String[0]
					: scope.split(","));

			String action = rs.getString("action");
			operation.setAction(Validators.isEmpty(action) ? new String[0]
					: action.split(","));

			operation.setState(rs.getInt("state"));
			operation.setLabel(rs.getString("label"));

			return operation;
		}
	}

	/**
	 * GroupPerm多条结果集
	 *
	 * @author xuan
	 */
	private static class GroupPermMultiRowMapper implements MultiRowMapper<GroupPermission> {
		@Override
		public GroupPermission mapRow(ResultSet rs, int rowNum) throws SQLException {
			GroupPermission groupPerm = new GroupPermission();
			groupPerm.setGroupId(rs.getString("group_id"));
			groupPerm.setAuthOperationId(rs.getString("auth_operation_id"));
			groupPerm.setPermission(rs.getInt("permission"));
			return groupPerm;
		}
	}

}
